home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / rayshade / libshade / picture.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  10KB  |  441 lines

  1. /*
  2.  * picture.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: picture.c,v 4.0.1.2 92/02/07 09:22:20 cek Exp Locker: cek $
  17.  *
  18.  * $Log:    picture.c,v $
  19.  * Revision 4.0.1.2  92/02/07  09:22:20  cek
  20.  * patch6: Fixed typo in MTV error message.
  21.  * 
  22.  * Revision 4.0.1.1  92/01/10  16:28:28  cek
  23.  * patch3: Added check for nonexistent patial image file.
  24.  * patch3: Fixed declaration of nrow in count_rle_rows().
  25.  * patch3: Changed level of several error messages.
  26.  * 
  27.  * Revision 4.0  91/07/17  14:47:00  kolb
  28.  * Initial version.
  29.  * 
  30.  */
  31. #include "rayshade.h"
  32. #include "picture.h"
  33. #include "viewing.h"
  34. #include "options.h"
  35. #include "stats.h"
  36.  
  37. #undef URT
  38.  
  39. #ifdef URT
  40. unsigned char **outptr;        /* Output buffer */
  41. static int count_rle_rows();
  42. #endif
  43.  
  44. /*
  45.  * Convert floating-point (0.-1.) to unsigned char (0-255), with no gamma
  46.  * correction.
  47.  */
  48. unsigned char
  49. correct(x)
  50. Float x;
  51. {
  52.     /*
  53.      * Truncate values < 0 or > 1.
  54.      */
  55.     if (x < 0)
  56.         return 0;
  57.     if (x > 1.)
  58.         return 255;
  59.     return (unsigned char)(x * 255.);
  60. }
  61.  
  62. #ifdef URT
  63. /*
  64.  * Open image file and write RLE header.
  65.  */
  66. void
  67. PictureStart(argv)
  68. char **argv;
  69. {
  70.     char gammacom[40];
  71.  
  72.     if (Options.framenum != Options.startframe) {
  73.         /*
  74.          * We've been here before;
  75.          * write a new header and return.
  76.          */
  77.         rle_put_setup(&rle_dflt_hdr);
  78.         return;
  79.     }
  80.     /*
  81.      * If Appending, then we know that outfile is valid, 'cause
  82.      * we've already read its header.
  83.      */
  84.     if (Options.appending) {
  85.         Options.pictfile = fopen(Options.imgname, "a");
  86.         if (Options.pictfile == (FILE *)0)
  87.             RLerror(RL_PANIC, "Cannot append to %s?!\n",
  88.                     Options.imgname);
  89.         rle_dflt_hdr.rle_file = Options.pictfile;
  90.         rle_put_init(&rle_dflt_hdr);
  91.     } else {
  92.         /*
  93.          * Starting image from scatch.
  94.          */
  95.         if (Options.imgname) {
  96.             Options.pictfile = fopen(Options.imgname, "w");
  97.             if (Options.pictfile == (FILE *)NULL)
  98.                 RLerror(RL_ABORT,"Cannot open %s for writing.",
  99.                     Options.imgname);
  100.         } else
  101.             Options.pictfile = stdout;
  102.  
  103.         rle_dflt_hdr.xmax = Screen.maxx;
  104.         rle_dflt_hdr.ymax = Screen.maxy;
  105.         rle_dflt_hdr.xmin = Screen.minx;
  106.         rle_dflt_hdr.ymin = Screen.miny;
  107.         rle_dflt_hdr.alpha = Options.alpha;
  108.         if (Options.alpha)
  109.             RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA);
  110.         if (Options.exp_output) {
  111.             RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE + 1);
  112.             rle_dflt_hdr.ncolors = 4;
  113.             rle_putcom("exponential_data", &rle_dflt_hdr);
  114.         }
  115.         else
  116.             rle_dflt_hdr.ncolors = 3;
  117.         /*
  118.           * Document image gamma in RLE comment area.
  119.          * Options.gamma has been inverted.
  120.           */
  121.         (void)sprintf(gammacom, "display_gamma=%g", 1./Options.gamma);
  122.         rle_putcom(gammacom, &rle_dflt_hdr);
  123.         /*
  124.           * Document command line in RLE history.
  125.           */
  126.         rle_addhist(argv, (rle_hdr *)0, &rle_dflt_hdr);
  127.         rle_dflt_hdr.rle_file = Options.pictfile;
  128.         rle_put_setup(&rle_dflt_hdr);
  129.         /*
  130.           * Flush the header.  If we don't, and LINDA forks off
  131.           * a bunch of workers, strange things will happen (they'll
  132.           * all flush the buffer when they die, and you end up with
  133.           * lots of headers at the end of the file).
  134.           */
  135.         (void)fflush(rle_dflt_hdr.rle_file);
  136.     }
  137.  
  138.     if (rle_row_alloc(&rle_dflt_hdr, &outptr) < 0)
  139.         RLerror(RL_PANIC, "Unable to allocate image memory.\n");
  140. }
  141.  
  142. /*
  143.  * Read RLE header to which we are appending in order determine
  144.  * old resolution, window location, and the like.
  145.  */
  146. void
  147. PictureSetWindow()
  148. {
  149.     if (Options.imgname == (char *)NULL)
  150.         RLerror(RL_ABORT,
  151.             "No partially-completed image file specified.\n");
  152.  
  153.     /*
  154.      * Open image and read RLE header.
  155.      */
  156.     Options.pictfile = fopen(Options.imgname, "r");
  157.     if (Options.pictfile == (FILE *)NULL) {
  158.         RLerror(RL_ABORT, "Cannot open image file %s.\n",
  159.                     Options.imgname);
  160.     }
  161.     rle_dflt_hdr.rle_file = Options.pictfile;
  162.     rle_get_setup_ok(&rle_dflt_hdr, "rayshade", Options.imgname);
  163.  
  164.     /*
  165.      * If user specified a window that does not match what's in
  166.      * the header, complain.
  167.     if (Screen.minx != UNSET && Screen.minx != rle_dflt_hdr.xmin ||
  168.         Screen.miny != UNSET && Screen.miny != rle_dflt_hdr.ymin ||
  169.         Screen.maxx != UNSET && Screen.maxx != rle_dflt_hdr.xmax ||
  170.         Screen.maxy != UNSET && Screen.maxy != rle_dflt_hdr.ymax)
  171.         RLerror(RL_ADVISE, "Image window: %d - %d, %d - %d.\n",
  172.             rle_dflt_hdr.xmin, rle_dflt_hdr.xmax,
  173.             rle_dflt_hdr.ymin, rle_dflt_hdr.ymax);
  174.      */
  175.     /*
  176.      * Set window.
  177.      */
  178.     Screen.minx = rle_dflt_hdr.xmin;
  179.     Screen.miny = rle_dflt_hdr.ymin;
  180.     Screen.maxx = rle_dflt_hdr.xmax;
  181.     Screen.maxy = rle_dflt_hdr.ymax;
  182.  
  183.     /*
  184.      * Set alpha.  Warn the user if the alpha option doesn't reflect
  185.      * what's already been rendered.
  186.      */
  187.     if (Options.alpha != rle_dflt_hdr.alpha)
  188.         RLerror(RL_WARN, "Image %s %s an alpha channel.\n",
  189.             Options.imgname,
  190.             rle_dflt_hdr.alpha ? "has" : "does not have");
  191.  
  192.     Options.alpha = rle_dflt_hdr.alpha;
  193.  
  194.     /*
  195.      * Determine number of scanlines written to file.
  196.      */
  197.     Screen.miny += count_rle_rows(&rle_dflt_hdr);
  198.     if (Screen.miny >= Screen.maxy) {
  199.         fprintf(stderr, "\"%s\" is a complete image.\n",
  200.             Options.imgname);
  201.         exit(0);
  202.     }
  203.     fprintf(Stats.fstats,"Continuing \"%s\" at scanline #%d.\n",
  204.         Options.imgname, Screen.miny);
  205.     (void)fclose(Options.pictfile);
  206. }
  207.  
  208. static int
  209. count_rle_rows( hdr )
  210. rle_hdr *hdr;
  211. {
  212.     rle_op **raw;
  213.     int *nraw, y, ynext;
  214.  
  215.     if (rle_raw_alloc( hdr, &raw, &nraw ) < 0)  {
  216.         RLerror(RL_PANIC,
  217.             "Unable to allocate memory in count_rle_rows.\n");
  218.     }
  219.  
  220.     y = hdr->ymin;
  221.     while ((ynext = rle_getraw( hdr, raw, nraw )) != 32768) {
  222.         y = ynext+1;
  223.         rle_freeraw( hdr, raw, nraw );
  224.     }
  225.  
  226.     /* Free memory. */
  227.     rle_raw_free( hdr, raw, nraw );
  228.  
  229.     return y - hdr->ymin;
  230. }
  231.  
  232. /*
  233.  * Write a scanline of output.
  234.  * "buf" is an array of Color structures of size Screen.xsize.  Each color
  235.  * component is normalized to [0, 1.].
  236.  */
  237. void
  238. PictureWriteLine(buf)
  239. Pixel *buf;
  240. {
  241.     register int i, chan;
  242.     float floats[3];
  243.     rle_pixel pixels[4];
  244.  
  245.     for(i = 0; i < Screen.xsize; i++) {
  246.         if (!Options.exp_output) {
  247.             /*
  248.              * Scale colors to fit unsigned char and check for
  249.              * over/underflow.
  250.              */
  251.             outptr[0][i] = CORRECT(buf[i].r);
  252.             outptr[1][i] = CORRECT(buf[i].g);
  253.             outptr[2][i] = CORRECT(buf[i].b);
  254.         } else {
  255.             /*
  256.              * Convert 3 floats to 4 unsigned chars for
  257.              * 'exponential_data' RLE file.
  258.              */
  259.             floats[0] = GAMMACORRECT(buf[i].r);
  260.             floats[1] = GAMMACORRECT(buf[i].g);
  261.             floats[2] = GAMMACORRECT(buf[i].b);
  262.             float_to_exp( 3, floats, pixels );
  263.             for (chan = 0; chan <= 3; chan++)
  264.                 outptr[chan][i] = pixels[chan];
  265.         }
  266.         if (Options.alpha)
  267.             /*
  268.              * Don't gamma correct alpha channel.
  269.              */
  270.             outptr[-1][i] = correct(buf[i].alpha);
  271.     }
  272.     rle_putrow(outptr, Screen.xsize, &rle_dflt_hdr);
  273. }
  274.  
  275. /*
  276.  * End the frame.
  277.  */
  278. void
  279. PictureFrameEnd()
  280. {
  281.     rle_puteof(&rle_dflt_hdr);
  282. }
  283.  
  284. /*
  285.  * Close image file.
  286.  */
  287. void
  288. PictureEnd()
  289. {
  290.     (void)fclose(Options.pictfile);
  291. }
  292.  
  293. #else /* !URT */
  294.  
  295. #define SGI_RGB
  296. #ifndef SGI_RGB
  297. void
  298. PictureStart(argv)
  299. char **argv;
  300. {
  301.     if (Options.imgname) {
  302.         Options.pictfile = fopen(Options.imgname, "w");
  303.         if (Options.pictfile == (FILE *)NULL)
  304.             RLerror(RL_ABORT, "Cannot open %s for writing.",
  305.                 Options.imgname);
  306.     } else
  307.         Options.pictfile = stdout;
  308.  
  309.     fprintf(Options.pictfile,"%d %d\n",Screen.xsize, Screen.ysize);
  310.  
  311.     (void)fflush(Options.pictfile);
  312. }
  313.  
  314. void
  315. PictureWriteLine(buf)
  316. Pixel *buf;
  317. {
  318.     register int i;
  319.  
  320.     for (i = 0; i < Screen.xsize; i++) {
  321.         (void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
  322.         (void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
  323.         (void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
  324.     }
  325.     (void)fflush(Options.pictfile);
  326. }
  327.  
  328. void
  329. PictureFrameEnd()
  330. {
  331.     /*
  332.      * Don't do anything -- generic format has no end-of-image marker.
  333.      */
  334. }
  335.  
  336. void
  337. PictureEnd()
  338. {
  339.     (void)fclose(Options.pictfile);
  340. }
  341.  
  342. #else
  343.  
  344. #include <gl/image.h>
  345.  
  346. static IMAGE *image;
  347. static int curRow;
  348.  
  349. void
  350. PictureStart(argv)
  351. char **argv;
  352. {
  353.         char *tempname = "rayshade.rgb";
  354.         char *filename;
  355.         unsigned int xsize,ysize,zsize=3,dim=3;
  356.         static int nFrame=0;
  357.  
  358.     if (!Options.imgname) 
  359.            filename = tempname;
  360.         else{
  361.            if(nFrame)
  362.                sprintf(filename,"%s_%04d",Options.imgname,nFrame);
  363.            else
  364.                filename = Options.imgname;
  365.         }
  366.         curRow = 0;
  367.         xsize = Screen.xsize;
  368.         ysize = Screen.ysize;
  369.         image = iopen(filename, "w", RLE(1), dim, xsize, ysize, zsize);
  370.         if (image == (IMAGE *)NULL)
  371.         RLerror(RL_ABORT, "Cannot open %s for writing.",
  372.                 Options.imgname);
  373.     nFrame++;
  374. }
  375.  
  376. void
  377. PictureWriteLine(buf)
  378. Pixel *buf;
  379. {
  380.         register short *red,*green,*blue,*end;
  381.         static short *redbuf,*greenbuf,*bluebuf;
  382.         Pixel *pixel;
  383.         static short rowSize=0;
  384.  
  385.         if(rowSize < Screen.xsize)
  386.         {
  387.             if(!rowSize)
  388.             {
  389.                 redbuf   = malloc(Screen.xsize * sizeof(short));
  390.                 greenbuf = malloc(Screen.xsize * sizeof(short));
  391.                 bluebuf  = malloc(Screen.xsize * sizeof(short));
  392.             }else{
  393.                 redbuf   = realloc(red, Screen.xsize * sizeof(short));
  394.                 greenbuf = realloc(green, Screen.xsize * sizeof(short));
  395.                 bluebuf  = realloc(blue, Screen.xsize * sizeof(short));
  396.             }
  397.             rowSize = Screen.xsize;
  398.         }
  399.         red = redbuf ; green = greenbuf ; blue = bluebuf;
  400.         end = &redbuf[Screen.xsize];
  401.         pixel = buf;
  402.         while (red < end)
  403.         {
  404.             *red   = (short)CORRECT(pixel->r);
  405.             *green = (short)CORRECT(pixel->g);
  406.             *blue  = (short)CORRECT(pixel->b);
  407.             red++; green++; blue++; pixel++;
  408.         }
  409.         putrow(image, redbuf, Screen.ysize-curRow-1, 0);
  410.         putrow(image, greenbuf, Screen.ysize-curRow-1, 1);
  411.         putrow(image, bluebuf, Screen.ysize-curRow-1, 2);
  412.         curRow++;
  413. }
  414.  
  415. void
  416. PictureFrameEnd()
  417. {
  418.     iclose(image);
  419. }
  420.  
  421. void
  422. PictureEnd()
  423. {
  424.     iclose(image);
  425. }
  426.  
  427. void
  428. PictureSetWindow()
  429. {
  430. }
  431. rle_get_setup()
  432. {
  433. }
  434. rle_getrow()
  435. {
  436. }
  437.  
  438.  
  439. #endif /* SGI */
  440. #endif /* URT */
  441.